---
title: 包管理与生态系统
description: 对比 Python 和 JavaScript 包管理系统，理解 npm/yarn 与 pip 的差异，掌握 JavaScript 生态系统导航技巧
---

# 模块 09：包管理与生态系统

## 学习目标

完成本模块后，你将能够：
- 理解 pip 和 npm/yarn 之间的差异
- 掌握 JavaScript 项目中的依赖管理
- 对比虚拟环境与 node_modules
- 导航 JavaScript 包生态系统
- 实施依赖管理的安全最佳实践

## 包管理器：pip vs npm/yarn

### Python：pip 和虚拟环境

在 Python 中，你熟悉的方式：

<PythonEditor title="Python 包管理" compare={true}>
```python !! py
# requirements.txt
requests==2.28.1
django==4.1.0
pytest==7.1.0

# 安装包
# pip install -r requirements.txt

# 虚拟环境
# python -m venv venv
# source venv/bin/activate (Linux/Mac)
# venv\Scripts\activate (Windows)

import requests
import django
from django.http import JsonResponse

def fetch_data():
    response = requests.get('https://api.example.com/data')
    return response.json()
```

```javascript !! js
// package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "dependencies": {
    "axios": "^1.1.0",
    "express": "^4.18.0"
  },
  "devDependencies": {
    "jest": "^29.0.0"
  }
}

// 安装包
// npm install 或 yarn install

// 无需虚拟环境 - 使用 node_modules/
const axios = require('axios');
const express = require('express');

async function fetchData() {
    const response = await axios.get('https://api.example.com/data');
    return response.data;
}
```
</PythonEditor>

### 主要差异

| 方面 | Python (pip) | JavaScript (npm/yarn) |
|------|-------------|----------------------|
| **配置文件** | requirements.txt | package.json |
| **锁定文件** | 无（pip-tools 有 Pipfile.lock） | package-lock.json / yarn.lock |
| **安装方式** | 默认全局 | 默认本地（node_modules） |
| **虚拟环境** | 手动（venv, virtualenv） | 自动（node_modules） |
| **版本格式** | `==2.28.1`（精确版本） | `^1.1.0`（语义化版本范围） |

## 依赖管理

### 语义化版本控制（SemVer）

<PythonEditor title="版本管理" compare={true}>
```python !! py
# Python：生产环境通常使用精确版本
# requirements.txt
django==4.1.0      # 精确版本
requests>=2.28.0   # 最小版本
numpy~=1.21.0      # 兼容版本

# pip freeze > requirements.txt
# 创建精确版本以确保可重现性

# 开发环境可能使用：
# django>=4.1.0,<5.0.0
```

```javascript !! js
// JavaScript：默认使用语义化版本控制
// package.json
{
  "dependencies": {
    "express": "^4.18.0",    // ^4.18.0 到 <5.0.0
    "lodash": "~4.17.21",    // ~4.17.21 到 <4.18.0
    "react": "18.2.0"        // 精确版本
  }
}

// package-lock.json 自动锁定精确版本
// yarn.lock 为 yarn 做同样的事情

// 版本范围：
// ^1.2.3 := >=1.2.3 <2.0.0 (兼容版本)
// ~1.2.3 := >=1.2.3 <1.3.0 (相近版本)
// 1.2.3  := 精确 1.2.3
```
</PythonEditor>

### 安装和管理包

<PythonEditor title="包安装" compare={true}>
```python !! py
# Python 包安装
# pip install requests
# pip install django==4.1.0
# pip install -e .  # 开发安装
# pip uninstall requests
# pip list
# pip show requests
# pip check  # 检查冲突

# 创建 requirements.txt
# pip freeze > requirements.txt

# 从 requirements.txt 安装
# pip install -r requirements.txt

# 升级包
# pip install --upgrade requests
# pip list --outdated
```

```javascript !! js
// npm 命令
// npm install express
// npm install express@4.18.0  # 特定版本
// npm install -g nodemon      # 全局安装
// npm uninstall express
// npm list
// npm info express
// npm audit                   # 安全审计

// yarn 命令（替代方案）
// yarn add express
// yarn add express@4.18.0
// yarn global add nodemon
// yarn remove express
// yarn list
// yarn info express
// yarn audit

// package.json 中的包脚本
{
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js",
    "test": "jest",
    "build": "webpack"
  }
}

// 运行脚本：npm run dev 或 yarn dev
```
</PythonEditor>

## 项目结构与配置

### Python vs JavaScript 项目结构

<PythonEditor title="项目结构" compare={true}>
```python !! py
# Python 项目结构
my_python_project/
├── venv/                 # 虚拟环境
├── src/
│   └── my_package/
│       ├── __init__.py
│       └── main.py
├── tests/
│   └── test_main.py
├── requirements.txt      # 依赖
├── setup.py             # 包元数据
├── README.md
└── .gitignore

# Python 的 .gitignore
__pycache__/
*.pyc
venv/
.env
dist/
build/
*.egg-info/
```

```javascript !! js
// JavaScript 项目结构
my_js_project/
├── node_modules/        # 依赖（自动生成）
├── src/
│   └── index.js
├── tests/
│   └── index.test.js
├── package.json         # 项目元数据和依赖
├── package-lock.json    # 锁定文件（自动生成）
├── README.md
└── .gitignore

// JavaScript 的 .gitignore
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.env
dist/
build/
coverage/

// package.json 结构
{
  "name": "my-js-project",
  "version": "1.0.0",
  "description": "我的出色项目",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "test": "jest"
  },
  "dependencies": {},
  "devDependencies": {},
  "engines": {
    "node": ">=16.0.0"
  }
}
```
</PythonEditor>

## 包生态系统

### 发现和评估包

<PythonEditor title="包发现" compare={true}>
```python !! py
# Python：PyPI（Python 包索引）
# https://pypi.org/

# 流行的 Python 包：
import requests     # HTTP 库
import django      # Web 框架
import flask       # 轻量级 Web 框架
import numpy       # 数值计算
import pandas      # 数据处理
import pytest      # 测试框架
import click       # CLI 框架
import sqlalchemy  # ORM

# 评估包：
# - PyPI 下载量和星数
# - GitHub 活跃度
# - 文档质量
# - 社区支持
```

```javascript !! js
// JavaScript：npm 注册表
// https://www.npmjs.com/

// 流行的 JavaScript 包：
const express = require('express');      // Web 框架
const lodash = require('lodash');        // 工具库
const axios = require('axios');          // HTTP 客户端
const moment = require('moment');        // 日期库
const validator = require('validator');  // 验证
const mongoose = require('mongoose');    // MongoDB ODM
const jest = require('jest');           // 测试框架
const commander = require('commander');  // CLI 框架

// 评估包：
// - npm 周下载量
// - GitHub 星数和活跃度
// - npm audit 安全检查
// - 打包大小影响
// - TypeScript 支持
// - 维护状态

// 有用的评估命令：
// npm info package-name
// npm audit
// npx bundle-phobia package-name  # 打包大小
```
</PythonEditor>

### 安全和最佳实践

<PythonEditor title="安全最佳实践" compare={true}>
```python !! py
# Python 安全实践
# pip check  # 检查依赖冲突
# pip-audit  # 安全漏洞扫描器
# safety check  # 另一个安全扫描器

# 保持依赖更新
# pip list --outdated
# pip install --upgrade package-name

# 生产环境使用精确版本
# requirements.txt 应该有精确版本
django==4.1.0
requests==2.28.1

# 使用虚拟环境进行隔离
# python -m venv venv
# source venv/bin/activate

# 环境变量使用示例
import os
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.getenv('API_KEY')
```

```javascript !! js
// JavaScript 安全实践
// npm audit  # 检查漏洞
// npm audit fix  # 自动修复漏洞
// yarn audit  # Yarn 等价命令

// 保持依赖更新
// npm outdated
// npm update package-name
// npx npm-check-updates  # 检查主版本更新

// 使用锁定文件确保可重现构建
// package-lock.json (npm)
// yarn.lock (yarn)

// 环境变量
require('dotenv').config();
const API_KEY = process.env.API_KEY;

// 安全工具
// npm install --save-dev eslint-plugin-security
// npx snyk test  # Snyk 安全测试

// package.json 安全配置
{
  "scripts": {
    "audit": "npm audit",
    "audit-fix": "npm audit fix",
    "security-check": "npx snyk test"
  },
  "engines": {
    "node": ">=16.0.0",
    "npm": ">=8.0.0"
  }
}
```
</PythonEditor>

## 高级包管理

### Monorepo 和工作空间

<PythonEditor title="Monorepo 管理" compare={true}>
```python !! py
# Python：原生 monorepo 支持有限
# 通常使用工具如：
# - pants（由 Twitter 开发）
# - bazel
# - poetry with workspace plugin

# 多包项目结构
my_monorepo/
├── packages/
│   ├── package_a/
│   │   ├── setup.py
│   │   └── requirements.txt
│   └── package_b/
│       ├── setup.py
│       └── requirements.txt
├── shared_requirements.txt
└── setup.py

# 手动依赖管理
# 每个包都有自己的 requirements.txt
# 共享依赖在根目录 requirements.txt
```

```javascript !! js
// JavaScript：原生工作空间支持

// package.json（根目录）
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "devDependencies": {
    "lerna": "^5.0.0"
  }
}

// packages/package-a/package.json
{
  "name": "@myorg/package-a",
  "version": "1.0.0",
  "dependencies": {
    "@myorg/package-b": "1.0.0",
    "lodash": "^4.17.21"
  }
}

// 工作空间命令
// npm install  # 安装所有工作空间依赖
// npm run test --workspaces  # 在所有包中运行测试
// npm run build --workspace=@myorg/package-a

// Lerna 用于高级 monorepo 管理
// npx lerna bootstrap  # 安装依赖
// npx lerna run test   # 跨包运行命令
// npx lerna publish    # 发布包
```
</PythonEditor>

### 发布包

<PythonEditor title="包发布" compare={true}>
```python !! py
# Python：发布到 PyPI
# setup.py
from setuptools import setup, find_packages

setup(
    name="my-awesome-package",
    version="1.0.0",
    description="一个出色的 Python 包",
    author="你的名字",
    author_email="your.email@example.com",
    packages=find_packages(),
    install_requires=[
        "requests>=2.28.0",
        "click>=8.0.0"
    ],
    python_requires=">=3.8",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
)

# 发布步骤：
# python setup.py sdist bdist_wheel
# twine upload dist/*
```

```javascript !! js
// JavaScript：发布到 npm

// package.json
{
  "name": "my-awesome-package",
  "version": "1.0.0",
  "description": "一个出色的 JavaScript 包",
  "main": "lib/index.js",
  "module": "es/index.js",
  "types": "lib/index.d.ts",
  "author": "你的名字 <your.email@example.com>",
  "license": "MIT",
  "keywords": ["javascript", "utility"],
  "repository": {
    "type": "git",
    "url": "https://github.com/yourname/my-awesome-package"
  },
  "files": [
    "lib/",
    "es/",
    "README.md"
  ],
  "scripts": {
    "build": "rollup -c",
    "prepublishOnly": "npm run build"
  },
  "peerDependencies": {
    "react": ">=16.8.0"
  },
  "engines": {
    "node": ">=14.0.0"
  }
}

// 发布步骤：
// npm login
// npm publish
// npm version patch  # 版本升级
// npm publish

// 作用域包（推荐用于组织）
// @myorg/my-package
```
</PythonEditor>

## 实战练习

### 练习 1：包迁移

将 Python 项目结构转换为 JavaScript：

<PythonEditor title="练习：项目迁移">
```python !! py
# 给定这个 Python 项目结构：
my_api/
├── venv/
├── src/
│   ├── __init__.py
│   ├── api.py
│   └── utils.py
├── tests/
│   └── test_api.py
├── requirements.txt
└── setup.py

# requirements.txt 内容：
flask==2.2.0
requests==2.28.1
pytest==7.1.0
python-dotenv==0.19.0

# 任务：创建等价的 JavaScript 项目结构
# 包含适当的 package.json 和依赖
```

```javascript !! js
// 解决方案：JavaScript 项目结构
my_api/
├── node_modules/        # 自动生成
├── src/
│   ├── api.js
│   └── utils.js
├── tests/
│   └── api.test.js
├── package.json
├── package-lock.json    # 自动生成
└── .env

// package.json 解决方案：
{
  "name": "my-api",
  "version": "1.0.0",
  "description": "我的 API 项目",
  "main": "src/api.js",
  "scripts": {
    "start": "node src/api.js",
    "dev": "nodemon src/api.js",
    "test": "jest",
    "test:watch": "jest --watch"
  },
  "dependencies": {
    "express": "^4.18.0",
    "axios": "^1.1.0",
    "dotenv": "^16.0.0"
  },
  "devDependencies": {
    "jest": "^29.0.0",
    "nodemon": "^2.0.0"
  },
  "engines": {
    "node": ">=16.0.0"
  }
}
```
</PythonEditor>

### 练习 2：依赖审计

<PythonEditor title="练习：安全审计">
```python !! py
# Python 安全检查
# pip install safety
# safety check
# pip-audit

# 示例漏洞依赖检查
import requests
import flask
import sqlalchemy

# 检查已知漏洞：
# 1. 运行安全扫描器
# 2. 更新有漏洞的包
# 3. 查看安全公告
```

```javascript !! js
// JavaScript 安全审计
// npm audit
// yarn audit

// 有潜在问题的示例 package.json
{
  "dependencies": {
    "lodash": "4.17.20",      // 可能存在漏洞
    "express": "4.17.0",      // 过时版本
    "axios": "0.21.0"         // 已知漏洞
  }
}

// 修复漏洞：
// npm audit fix
// npm update lodash
// npm install lodash@latest

// 自动化安全检查：
{
  "scripts": {
    "security-check": "npm audit && npx snyk test",
    "update-deps": "npx npm-check-updates -u && npm install"
  }
}
```
</PythonEditor>

## 最佳实践总结

### 包管理最佳实践

1. **使用锁定文件**确保可重现构建
2. **定期安全审计**使用 `npm audit`
3. **保持依赖更新**但要充分测试
4. **生产环境使用精确版本**
5. **最小化依赖**- 避免不必要的包
6. **添加依赖前检查包质量**

### 生态系统导航技巧

1. **检查包流行度**和维护状态
2. **阅读文档**和示例
3. **检查 TypeScript 支持**（如果使用 TypeScript）
4. **考虑打包大小**（前端包）
5. **评估替代方案**后再选择包
6. **使用已建立的、维护良好的包**

## 下一步

在下一个模块中，我们将探索测试框架和调试技术，对比 Python 的 unittest/pytest 与 JavaScript 的 Jest 和其他测试工具。

我们将涵盖的关键主题：
- Jest vs pytest 对比
- 单元测试模式
- 模拟和存根
- 集成测试
- 调试工具和技术

---

*继续学习 [模块 10：测试框架与调试技巧 →](/docs/py2js/module-10-testing-debugging)*
